import { 
  Inject, 
  Injector, 
  Plugin, 
  CommandType, 
  ICommandService, 
  IUndoRedoService, 
  IUniverInstanceService, 
  UniverInstanceType,
  covertCellValues,
  sequenceExecute
} from '@univerjs/core'
import { FolderSingle } from '@univerjs/icons'
import { ComponentManager, IMenuManagerService, MenuItemType, RibbonStartGroup } from '@univerjs/ui'
import type { IAccessor, ICommand, ICellData } from '@univerjs/core'
import type { 
  ISetRangeValuesMutationParams, 
  ISetWorksheetColumnCountMutationParams, 
  ISetWorksheetRowCountMutationParams 
} from '@univerjs/sheets'
import {
  SetRangeValuesMutation,
  SetRangeValuesUndoMutationFactory,
  SetWorksheetColumnCountMutation,
  SetWorksheetColumnCountUndoMutationFactory,
  SetWorksheetRowCountMutation,
  SetWorksheetRowCountUndoMutationFactory,
} from '@univerjs/sheets'
import type { IMutationInfo } from '@univerjs/core'

/**
 * Import CSV Plugin
 * 基于Univer官方文档的CSV导入插件
 */
class ImportCSVPlugin extends Plugin {
  static override pluginName = 'import-csv-plugin'

  constructor(
    // inject injector, required
    @Inject(Injector) override readonly _injector: Injector,
    // inject menu service, to add toolbar button
    @Inject(IMenuManagerService) private readonly menuManagerService: IMenuManagerService,
    // inject component manager, to register icon component
    @Inject(ComponentManager) private readonly componentManager: ComponentManager,
    // inject command service, to register command handler
    @Inject(ICommandService) private readonly commandService: ICommandService,
  ) {
    super()
  }

  /** Plugin onStarting lifecycle */
  onStarting() {
    console.log('ImportCSVPlugin onStarting')
    
    // register icon component
    this.componentManager.register('FolderSingle', FolderSingle)

    const buttonId = 'import-csv-button'

    const menuItemFactory = () => ({
      id: buttonId, // button id, also used as the click event command id
      title: 'Import CSV', // button text
      tooltip: 'Import CSV', // tooltip text
      icon: 'FolderSingle', // button icon name
      type: MenuItemType.BUTTON, // button type
    })

    this.menuManagerService.mergeMenu({
      [RibbonStartGroup.OTHERS]: {
        [buttonId]: {
          order: 10,
          menuItemFactory,
        },
      },
    })

    const command: ICommand = {
      type: CommandType.OPERATION,
      // command id, same as menu button id
      id: buttonId,
      handler: (accessor: IAccessor) => {
        console.log('Import CSV button clicked')
        return this.waitUserSelectCSVFile(accessor)
      },
    }

    // register command handler
    this.commandService.registerCommand(command)
  }

  /**
   * 等待用户选择CSV文件
   */
  private waitUserSelectCSVFile(accessor: IAccessor): Promise<boolean> {
    return new Promise((resolve) => {
      const input = document.createElement('input')
      input.type = 'file'
      input.accept = '.csv'
      input.style.display = 'none'
      
      input.onchange = async (event) => {
        const target = event.target as HTMLInputElement
        const file = target.files?.[0]
        
        if (!file) {
          resolve(false)
          return
        }

        try {
          const csvData = await this.parseCSVFile(file)
          const success = await this.importCSVToSheet(accessor, csvData)
          resolve(success)
        } catch (error) {
          console.error('CSV import failed:', error)
          alert('CSV导入失败: ' + (error instanceof Error ? error.message : String(error)))
          resolve(false)
        } finally {
          document.body.removeChild(input)
        }
      }

      input.oncancel = () => {
        document.body.removeChild(input)
        resolve(false)
      }

      document.body.appendChild(input)
      input.click()
    })
  }

  /**
   * 解析CSV文件
   */
  private async parseCSVFile(file: File): Promise<string[][]> {
    const text = await file.text()
    const lines = text.split('\n').filter(line => line.trim())
    
    const data: string[][] = []
    lines.forEach((line) => {
      // 简单的CSV解析，处理引号包围的值
      const values: string[] = []
      let currentValue = ''
      let inQuotes = false
      
      for (let i = 0; i < line.length; i++) {
        const char = line[i]
        
        if (char === '"') {
          if (inQuotes && line[i + 1] === '"') {
            // 转义的引号
            currentValue += '"'
            i++ // 跳过下一个引号
          } else {
            // 开始或结束引号
            inQuotes = !inQuotes
          }
        } else if (char === ',' && !inQuotes) {
          // 分隔符
          values.push(currentValue.trim())
          currentValue = ''
        } else {
          currentValue += char
        }
      }
      
      // 添加最后一个值
      values.push(currentValue.trim())
      data.push(values)
    })

    return data
  }

  /**
   * 将CSV数据导入到工作表
   */
  private async importCSVToSheet(accessor: IAccessor, csvData: string[][]): Promise<boolean> {
    try {
      // inject univer instance service
      const univerInstanceService = accessor.get(IUniverInstanceService)
      // get command service
      const commandService = accessor.get(ICommandService)
      // get undo redo service
      const undoRedoService = accessor.get(IUndoRedoService)

      // get current sheet
      const worksheet = (() => {
        try {
          const workbook = univerInstanceService.getCurrentUnitOfType(UniverInstanceType.UNIVER_SHEET)
          if (!workbook) return null
          const wb = workbook as any
          if (typeof wb.getActiveSheet === 'function') {
            return wb.getActiveSheet()
          } else if (typeof wb.getSheets === 'function') {
            const sheets = wb.getSheets()
            return sheets?.[0]
          }
          return null
        } catch (error) {
          console.warn('Failed to get active sheet:', error)
          return null
        }
      })()
      if (!worksheet) {
        throw new Error('No active worksheet found')
      }

      const unitId = worksheet.getUnitId()
      const subUnitId = worksheet.getSheetId()

      const rowsCount = csvData.length
      const colsCount = Math.max(...csvData.map(row => row.length), 0)

      const redoMutations: IMutationInfo[] = []
      const undoMutations: IMutationInfo[] = []

      // set sheet row count
      const setRowCountMutationRedoParams: ISetWorksheetRowCountMutationParams = {
        unitId,
        subUnitId,
        rowCount: rowsCount,
      }
      const setRowCountMutationUndoParams: ISetWorksheetRowCountMutationParams = SetWorksheetRowCountUndoMutationFactory(
        accessor,
        setRowCountMutationRedoParams,
      )
      redoMutations.push({ id: SetWorksheetRowCountMutation.id, params: setRowCountMutationRedoParams })
      undoMutations.push({ id: SetWorksheetRowCountMutation.id, params: setRowCountMutationUndoParams })

      // set sheet column count
      const setColumnCountMutationRedoParams: ISetWorksheetColumnCountMutationParams = {
        unitId,
        subUnitId,
        columnCount: colsCount,
      }
      const setColumnCountMutationUndoParams: ISetWorksheetColumnCountMutationParams = SetWorksheetColumnCountUndoMutationFactory(
        accessor,
        setColumnCountMutationRedoParams,
      )
      redoMutations.push({ id: SetWorksheetColumnCountMutation.id, params: setColumnCountMutationRedoParams })
      undoMutations.unshift({ id: SetWorksheetColumnCountMutation.id, params: setColumnCountMutationUndoParams })

      // parse csv to univer data
      const cellValue = covertCellValues(csvData, {
        startColumn: 0, // start column index
        startRow: 0, // start row index
        endColumn: colsCount - 1, // end column index
        endRow: rowsCount - 1, // end row index
      })

      // set sheet data
      const setRangeValuesMutationRedoParams: ISetRangeValuesMutationParams = {
        unitId,
        subUnitId,
        cellValue,
      }
      const setRangeValuesMutationUndoParams: ISetRangeValuesMutationParams = SetRangeValuesUndoMutationFactory(
        accessor,
        setRangeValuesMutationRedoParams,
      )
      redoMutations.push({ id: SetRangeValuesMutation.id, params: setRangeValuesMutationRedoParams })
      undoMutations.unshift({ id: SetRangeValuesMutation.id, params: setRangeValuesMutationUndoParams })

      const result = sequenceExecute(redoMutations, commandService)

      if (result.result) {
        undoRedoService.pushUndoRedo({
          unitID: unitId,
          undoMutations,
          redoMutations,
        })

        alert('CSV文件导入成功！')
        return true
      }

      return false
    } catch (error) {
      console.error('Import CSV to sheet failed:', error)
      throw error
    }
  }
}

export default ImportCSVPlugin
